Skip to content

fix: bound Redis usage idempotency cache - #738

Merged
kang-heewon merged 1 commit into
trunkfrom
fix/704-metering-idempotency-cache
Jun 14, 2026
Merged

fix: bound Redis usage idempotency cache#738
kang-heewon merged 1 commit into
trunkfrom
fix/704-metering-idempotency-cache

Conversation

@kang-heewon

@kang-heewon kang-heewon commented Jun 14, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #704.

RedisUsageStorage now keeps its process-local record idempotency short-circuit cache bounded. Expired local keys are pruned opportunistically during later quota writes/checks, and a full cache evicts the oldest local entries before accepting new unique keys. Redis remains the idempotency source of truth.

변경 사항

  • Added a bounded local record idempotency cache policy: 24-hour TTL in milliseconds, 10,000 max entries, and 60-second opportunistic prune interval.
  • Prunes expired local keys without requiring the same key to be queried again, and evicts oldest local entries when unique record ids would exceed the cap.
  • Added fake-timer regression coverage for TTL pruning and a size-cap regression for long-running high-cardinality processes.
  • Added a patch changeset for @croco/metering-core.

Verification

  • pnpm test --filter=@croco/metering-core - passed, 13 files / 156 tests. Pre-push full pnpm test also passed, 197 tasks.
  • pnpm typecheck --filter=@croco/metering-core - passed. Pre-push full pnpm typecheck also passed, 196 tasks.
  • pnpm check - passed.
  • pnpm exec changeset status --since origin/trunk - passed and reports patch bumps for @croco/metering-core and dependent packages.
  • git diff --cached --check - passed.

Self-review

  • Correctness/regression: PASS. Issue acceptance is covered by RedisUsageStorage.spec.ts fake-timer pruning and max-size tests; existing duplicate short-circuit behavior remains covered by the existing idempotency test.
  • API/security/compatibility/release: PASS. No public API, Redis key format, dependencies, package manifest, lockfile, or secret/env assumptions changed. Redis remains authoritative when a local cache entry is missing or evicted, and the changeset covers the publishable package behavior.
  • Maintainability/minimality: PASS. The patch is limited to RedisUsageStorage, its focused tests, and release metadata; it reuses the existing Map and adds a small local policy instead of a new dependency or cross-package abstraction.

Risk

Low. Processes that exceed 10,000 unique local record idempotency keys may perform more Redis evals for older duplicates after local eviction, but Redis idempotency still preserves correctness.

Summary by CodeRabbit

개선사항

  • Redis 기반 Idempotency 캐시에 자동 프루닝 기능이 추가되어 만료된 항목이 자동으로 정리됩니다.
  • 캐시 크기 제한이 도입되어 장시간 실행 프로세스에서 메모리 사용량이 제어됩니다.

테스트

  • Idempotency 캐시 만료 및 크기 제한 동작 검증을 위한 테스트가 추가되었습니다.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kang-heewon, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 49 minutes and 41 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 49bc29ae-6baf-4e04-be83-273c236f20cc

📥 Commits

Reviewing files that changed from the base of the PR and between cb5338f and b49666a.

📒 Files selected for processing (3)
  • .changeset/metering-idempotency-cache-pruning.md
  • packages/metering-core/src/libs/RedisUsageStorage.ts
  • packages/metering-core/src/tests/RedisUsageStorage.spec.ts
📝 Walkthrough

Walkthrough

RedisUsageStorage의 로컬 idempotency 캐시에 주기적 프루닝, 최대 엔트리 상한(RECORD_IDEMPOTENCY_CACHE_MAX_ENTRIES), 오래된 키 퇴출(evictOldestRecordedRecordKeys) 로직을 추가했습니다. hasRecordedRecordKeyrememberRecordIdempotencyKey 호출 시 만료 엔트리를 자동 제거하도록 동작이 변경되었으며, 관련 테스트 2건과 changeset이 추가되었습니다.

Changes

로컬 idempotency 캐시 프루닝 및 퇴출

Layer / File(s) Summary
캐시 상수·필드 및 프루닝/퇴출 로직
packages/metering-core/src/libs/RedisUsageStorage.ts
TTL·최대 엔트리·프루닝 주기 상수와 nextRecordIdempotencyCachePruneAt 필드를 추가했습니다. hasRecordedRecordKeypruneRecordedRecordKeysIfNeeded 호출 후 expiresAt으로 만료를 판단하도록 변경되었습니다. rememberRecordIdempotencyKey에 프루닝·퇴출 보조 메서드 3개(pruneRecordedRecordKeysIfNeeded, pruneExpiredRecordedRecordKeys, evictOldestRecordedRecordKeys)가 추가되어 캐시 포화 시 오래된 키를 제거한 뒤 신규 키를 등록합니다.
테스트 보강 및 changeset
packages/metering-core/src/tests/RedisUsageStorage.spec.ts, .changeset/metering-idempotency-cache-pruning.md
afterEach에서 vi.useRealTimers()로 Fake Timers를 정리하고, recordedRecordKeys 읽기 헬퍼와 createUsageRecord 헬퍼를 추가했습니다. Fake Timer를 이용해 만료된 로컬 키 제거와 캐시 크기 상한(10,000개) 준수를 검증하는 테스트 2건을 추가했으며, changeset에 동작 변경이 기록되었습니다.

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 변경 사항의 주요 내용을 명확하게 요약하고 있습니다. 'Redis usage idempotency cache'를 'bounded'로 제한하는 것이 핵심 변경입니다.
Linked Issues check ✅ Passed PR이 #704의 모든 요구사항을 충족합니다: (1) 만료된 키의 opportunistic pruning 구현 [#704], (2) 10,000 엔트리 제한으로 캐시 크기 상한 설정 [#704], (3) fake timer 기반 회귀 테스트 추가 [#704].
Out of Scope Changes check ✅ Passed 모든 변경사항이 #704의 범위 내입니다: RedisUsageStorage의 로컬 idempotency 캐시 bounded 메모리 관리 구현과 해당 테스트만 포함되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/704-metering-idempotency-cache

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

📊 Benchmark Results

❌ Some benchmarks failed

Benchmark p75 Threshold Baseline vs Baseline Status
CrocoApp benchmarks 3.2μs - - - ⚠️
EventBusConfig.start (10 handlers) 1.3μs - 9.0μs -85.1%
EventPublisher.publishNow single event 1.6μs - - - ⚠️
DefaultHandlerResolver.resolve × 10 0.1μs - 0.2μs -60.0%
Container.get singleton (cold) 1.0μs - 0.5μs +98.2%
Container.register × 50 components 10.4μs - 8.0μs +29.7%
Container.validate (50 components) 27.7μs - 25.0μs +10.7%
Container.get singleton (warm) 0.4μs - 0.3μs +26.7%
TelemetryRuntime benchmarks 1.9μs - 2.0μs -2.9%

Updated: 2026-06-14T21:57:01.878Z · Commit: 490464e

@kang-heewon
kang-heewon force-pushed the fix/704-metering-idempotency-cache branch from 1ce9db2 to efd17cf Compare June 14, 2026 21:31
@kang-heewon
kang-heewon force-pushed the fix/704-metering-idempotency-cache branch from efd17cf to b49666a Compare June 14, 2026 21:53
@kang-heewon
kang-heewon merged commit 76bc0df into trunk Jun 14, 2026
7 of 8 checks passed
@kang-heewon
kang-heewon deleted the fix/704-metering-idempotency-cache branch June 14, 2026 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[metering-core] RedisUsageStorage의 로컬 idempotency 캐시가 장기 프로세스에서 커질 수 있음

1 participant